      <h1 class="entry-title entry-title-single" itemprop="headline">ABAP 开发系列(07): 模块化 &#8211; 子程序</h1>

    <div class="entry-content entry-content-single entry-content-aside" itemprop="text">
      <p><b>4. 模块化（Modularization）</b></p>
<p><span class='wp_keywordlink'><a href="http://www.sapjx.com/tag/sap-abap" title="ABAP" target="_blank">ABAP</a></span> 主要有三种模块单元：</p>
<p>1).Event：事件<br />
2).<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/subroutine" title="查看Subroutine中的全部文章" target="_blank">Subroutine</a></span>：<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/abap-subroutine" title="查看子程序中的全部文章" target="_blank">子程序</a></span><br />
3).<span class='wp_keywordlink'><a href="http://www.sapjx.com/tag/function" title="Function" target="_blank">Function</a></span> module：功能模块</p>
<p>这里主要讲解的是第2种模块单元: <span class='wp_keywordlink'><a href="http://www.sapjx.com/tag/sap-abap" title="ABAP" target="_blank">ABAP</a></span>的 <b><span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/abap-subroutine" title="查看子程序中的全部文章" target="_blank">子程序</a></span> (<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/subroutine" title="查看Subroutine中的全部文章" target="_blank">Subroutine</a></span>)</b>。</p>
<p>它是包含在程序中的一段功能代码，单独作为一个小程序封装并包含在主程序中；</p>
<p>特别是主程序中多次用到的代码，可以抽离出来，放在<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/abap-subroutine" title="查看子程序中的全部文章" target="_blank">子程序</a></span>中，方便多次使用。</p>
<p>以便于分析与简化代码可读性，更主要的是能便于程序的维护。</p>
<p>&nbsp;<br />
<span id="more-264"></span><br />
<img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_07_subroutine.png" alt="abap_07_subroutine" width="437" height="268" class="alignnone size-full wp-image-506" /></p>
<p>&nbsp;</p>
<p><b>4.1 创建子程序</b></p>
<p>通过<b style="color:#c21825;">FORM … ENDFORM.</b> 语句可以实现子程序的定义。</p>
<p>定义完成后，在需要调用子程序的地方使用<b style="color:#c21825;"> PERFORM …</b> 语句来实现对子程序的调用：</p>
<p><b style="color:#c21825;">PERFORM sub. </b></p>
<p><b style="color:#c21825;">FORM sub.</b></p>
<p><b style="color:#c21825; padding-left:20px;">Subroutine Code… </b></p>
<p><b style="color:#c21825;">ENDFORM.</b></p>
<p>&nbsp;</p>
<p><b>4.2 子程序参数传递</b></p>
<p><b>4.2.1 形式参数与实际参数</b></p>
<p>主程序在调用子程序时，避免不了需要传递相应的参数。</p>
<p>定义在子程序中的参数为 <b>形式参数</b>；</p>
<p>主程序中调用子程序时传入的参数为 <b>实际参数</b>。</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_07_pass_paramerters.png" alt="abap_07_pass_paramerters" width="623" height="358" class="alignnone size-full wp-image-505" /></p>
<p>&nbsp;</p>
<p>在子程序中定义形式参数，可以通过下面几种方式：</p>
<p><strong>1）USING</strong></p>
<p><strong>2）CHANGING</strong></p>
<p><strong>3）TABLES</strong></p>
<p>&nbsp;</p>
<p><b>4.2.2 USING 传参</b></p>
<p>向子程序直接参数，在子程序中，传输的参数不能改变。</p>
<p>如若需要直接传值的，需要加上<b style="color:#c21825;">VALUE() </b>关键字，一般情况下，都是以引用方式传递：</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_07_using_value_demo.png" alt="abap_07_using_value_demo" width="398" height="359" class="alignnone size-full wp-image-504" /></p>
<p>&nbsp;</p>
<p><b>4.2.3 CHANGING 传参</b></p>
<p>通过子程序传输内表或参数，当程序执行成功后，执行结果会通过该表或参数返回给主程序。</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_07_change_value_demo.png" alt="abap_07_change_value_demo" width="434" height="333" class="alignnone size-full wp-image-265" /></p>
<p>&nbsp;</p>
<p><b>4.2.4 TABLES 传参</b></p>
<p>通过内表方式传输参数数据。</p>
<p>在定义形式参数时，在参数名后，需要声明其内表结构；</p>
<p><b style="color:#c21825;">FORM sub TABLES pt_mara STRUCTURE mara.</b></p>
<p><b style="color:#c21825; padding-left:20px;">..</b></p>
<p><b style="color:#c21825;">ENDFORM.</b></p>
<p>声明的内表结构，必须存在于数据字典中；</p>
<p>如果是自定义的结构，则需要带有HEADER LINE；</p>
<p>没有 HEADER LINE 的可以通过参考定义好的内表来操作：</p>
<p>&nbsp;</p>
<pre class="brush: abap;">
*主程序
* 定义内表，带有HEADER LINE
DATA: BEGIN OF tab OCCURS 10,
        F1 LIKE tabna-country,
        F2 LIKE tabna -name1,
      END OF tab.

DATA : X.

PERFORM sub1 TABLES tab USING  X.

* 子程序
FORM sub1 TABLES fred STRUCTURE tab USING Z.

LOOP AT fred.
  WRITE: / fred-F1, fred-F2.
ENDLOOP.

ENDFORM .

</pre>
<p>&nbsp;</p>
<p>参考定义好的内表操作：</p>
<pre class="brush: abap;">
* 主程序
TABLES: mara,marc.

TYPES: BEGIN OF ty_s_test,
         matnr type mara-matnr,
         werks type marc-werks,
       END OF ty_s_test.

DATA:  gt_test TYPE STANDARD TABLE OF ty_s_test.

* 调用子程序
PERFORM sub TABLES gt_test.

*子程序
FORM sub TABLES pt_test LIKE gt_test.

  …

ENDFORM.

</pre>
<p>注意的是，在子程序中内表的形式参数，都默认带有HEADER LINE。</p>
<p>所以LIKE 参考的内表不能带有HEADER LINE，不然无法通过语法的检查。</p>
<p>&nbsp;</p>
<p><b>4.2.5 </b><b>传输结构</b></p>
<p>由于USING可以传输引用，因此可以通过USING来传输结构；</p>
<p>当然只能通过Work Area或HEADER LINE来传输：</p>
<pre class="brush: abap;">
TABLES: tabna.

DATA: ztab LIKE tabna.
DATA: flag.

PERFORM sub1 USING tabna.   "只能传输 Work area
PERFORM sub1 USING ztab.    "这里传输整个ZTAB

FORM sub1 USING rec STRUCTURE tabna.

  WRITE: / rec-country,
           rec-name1.
ENDFORM.

</pre>
<p>&nbsp;</p>
<p><b>4.3 全局变量与局部变量</b></p>
<p>在主程序中定义的变量，可以用于全局，子程序中也可以引用；</p>
<p>在子程序中定义的变量，则只适用于子程序中，也就是局部变量，主程序则不能引用。</p>
<p>&nbsp;</p>
<pre class="brush: abap;">

*  全局变量
DATA: num(9) VALUE  '999999999'.
DATA: id   LIKE tabna-id,
      name LIKE tabna-name1.

…

PERFORM sub1.

…

*&#038;---------------------------------------------------------------------*
*&#038;      Form  Sub1
*&#038;---------------------------------------------------------------------*
FORM sub1.

* 局部变量
DATA: BEGIN OF tab OCCURS 10,
       Id    LIKE  tabna-id,
       name1 LIKE  tabna-name1,
      END OF tab.

* 可以引用全局变量 - 为全局变量赋值
Id = ‘000901’.

* 局部变量
Tab-id = id.
…

ENDFORM.

</pre>
<p>&nbsp;</p>
<p><b>4.6 </b><b>调用外部子程序</b></p>
<p>子程序不仅能在主程序中调用，也能被外部程序调用。</p>
<p>语句:</p>
<p><b style="color:#c21825; padding-left:20px;">PERFORM &lt;name&gt; (&lt;prog name&gt;) USING . . .</b></p>
<p><b>prog name</b>：该子程序所属的主程序名称。</p>
<p>&nbsp;</p>
<p>ZTEST020程序：</p>
<pre class="brush: abap;">
REPORT ZTEST020.
TABLES: TABNA, T001, T005.

…

START-OF-SELECTION.

  …

PERFORM sub1 (ZTEST021) …	.

…

</pre>
<p>&nbsp;</p>
<p>ZTEST021 程序：</p>
<pre class="brush: abap;">
REPORT ZTEST021.
TABLES : TABNA, T001, T001G.

 …

START-OF-SELECTION

 …

FORM SUB1 . . . .

  …

  NEW-PAGE.

  …
ENDFORM

</pre>
<p>&nbsp;<br />
&nbsp;</p>